package org.openea.eap.module.obpm.util.form;

import org.openbpm.base.core.util.BeanUtils;
import org.springframework.util.StringUtils;

import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public abstract class DateUtils
{
  static String DATE_FORMAT_DATETIME = "yyyy-MM-dd HH:mm:ss";




  static String DATE_FORMAT_DATE = "yyyy-MM-dd";




  static String DATE_FORMAT_DATETIME_NOSECOND = "yyyy-MM-dd HH:mm";




  static String DATE_FORMAT_TIME = "HH:mm:ss";




  static String DATE_FORMAT_TIME_NOSECOND = "HH:mm";




  static String DATE_FORMAT_TIMESTAMP = "yyyy-MM-dd HH:mm:ss.SSS";


  public static final String ISO_DATE_FORMAT = "yyyyMMdd";

  public static final String ISO_EXPANDED_DATE_FORMAT = "yyyy-MM-dd";

  public static final String ISO_TIME_FORMAT = "HHmmssSSSzzz";

  public static final String ISO_EXPANDED_TIME_FORMAT = "HH:mm:ss,SSSzzz";

  public static final String ISO_DATE_TIME_FORMAT = "yyyyMMdd'T'HHmmssSSSzzz";

  public static final String ISO_EXPANDED_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss,SSSzzz";

  public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";

  public static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

  public static final long ONE_SECOND = 1000L;

  public static final long ONE_MINUTE = 60000L;

  public static final long ONE_HOUR = 3600000L;

  public static final long ONE_DAY = 86400000L;

  public static final long ONE_WEEK = 604800000L;

  public static final long ONE_YEAR = 31536000000L;

  public static final Date LONG_BEFORE_TIME = string2Date("1970-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss");


  public static final Date LONG_AFTER_TIME = string2Date("2048-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss");


  public static final int SECOND = 0;


  public static final int MINUTE = 1;


  public static final int HOUR = 2;

  public static final int DAY = 3;

  public static final int MONTH = 4;

  public static final DateFormat DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_DATE);




  public static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATE_FORMAT_DATETIME);




  public static final DateFormat DATETIME_NOSECOND_FORMAT = new SimpleDateFormat(DATE_FORMAT_DATETIME_NOSECOND);




  public static final DateFormat TIME_FORMAT = new SimpleDateFormat(DATE_FORMAT_TIME);




  public static final DateFormat TIME_NOSECOND_FORMAT = new SimpleDateFormat(DATE_FORMAT_TIME_NOSECOND);




  public static final DateFormat TIMESTAMP_FORMAT = new SimpleDateFormat(DATE_FORMAT_TIMESTAMP);


  public static Date afterDays(Date date, long days) { return new Date(date.getTime() + 86400000L * days); }



  public static Date afterDays(long days) { return new Date(System.currentTimeMillis() + 86400000L * days); }



  public static Date afterDays(long time, long days) { return new Date(time + 86400000L * days); }


  public static Date afterDays(String date, long days) {
    Date dateTmp = parseDate(date);
    return afterDays(dateTmp, days);
  }


  public static Date afterHours(long hours) { return new Date(System.currentTimeMillis() + 3600000L * hours); }



  public static Date afterHours(long time, long hours) { return new Date(time + 3600000L * hours); }



  public static Date afterMilliseconds(long time, long milliseconds) { return new Date(time + milliseconds); }



  public static Date afterMinutes(long minutes) { return new Date(System.currentTimeMillis() + 60000L * minutes); }



  public static Date afterMinutes(long time, long minutes) { return new Date(time + 60000L * minutes); }



  public static Date afterSeconds(long seconds) { return new Date(System.currentTimeMillis() + 1000L * seconds); }



  public static Date afterSeconds(long time, long seconds) { return new Date(time + 1000L * seconds); }



  public static Date afterYears(long years) { return new Date(System.currentTimeMillis() + 31536000000L * years); }



  public static Date afterYears(long time, long years) { return new Date(time + 31536000000L * years); }









  public static Date convertDateString(String value) { return convertString(value, "yyyy-MM-dd"); }






















  public static Date convertString(String value) { return convertString(value, "yyyy-MM-dd HH:mm:ss"); }









  public static Date convertString(String value, String format) {
    SimpleDateFormat sdf = new SimpleDateFormat(format);
    if (value == null)
      return null;
    try {
      return sdf.parse(value);
    } catch (Exception e) {
      return null;
    }
  }















  public static String dateString(String d) {
    if (StringUtils.isEmpty(d) || d.length() != 8)
      return d;
    char[] array = d.toCharArray();
    char[] buff = new char[10];
    System.arraycopy(array, 0, buff, 0, 4);
    System.arraycopy(array, 4, buff, 5, 2);
    System.arraycopy(array, 6, buff, 8, 2);
    buff[7] = '-';
    buff[4] = '-';
    return new String(buff);
  }








  public static String formaDatetTime(Date date) { return DATETIME_FORMAT.format(date); }









  public static String format(Date date) {
    if (date instanceof Timestamp)
      return TIMESTAMP_FORMAT.format(date);
    if (date instanceof Time)
      return TIME_FORMAT.format(date);
    if (date instanceof Date) {
      return DATE_FORMAT.format(date);
    }
    return DATETIME_FORMAT.format(date);
  }









  public static String format(Date date, String style) {
    DateFormat dateFormat = new SimpleDateFormat(style);
    return dateFormat.format(date);
  }


  public static String formatDate(Date date) { return formatDate(date, "yyyy-MM-dd HH:mm:ss"); }


  public static String formatDate(Date date, DateFormat dateFormat) {
    if (date == null) {
      throw new IllegalArgumentException("date can not be null");
    }
    if (dateFormat == null) {
      throw new IllegalArgumentException("dateFormat can not be null");
    }
    return dateFormat.format(date);
  }


  public static String formatDate(Date date, String dateFormatPattern) { return formatDate(date, null, dateFormatPattern); }



  public static String formatDate(Date date, TimeZone zone) { return formatDate(date, zone, "yyyy-MM-dd HH:mm:ss"); }


  public static String formatDate(Date date, TimeZone zone, String dateFormatPattern) {
    DateFormat dateFormat = null;
    try {
      dateFormat = new SimpleDateFormat(dateFormatPattern);
    } catch (Exception ignore) {
      dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }
    if (zone != null)
      dateFormat.setTimeZone(zone);
    return formatDate(date, dateFormat);
  }








  public static String formatDate(long mills) throws Exception {
    try {
      if (mills == 0L)
        return "-";
      Date date = null;
      Calendar ca = Calendar.getInstance();
      ca.setTimeInMillis(mills);
      date = ca.getTime();


      SimpleDateFormat myformat = new SimpleDateFormat("yyyy-MM-dd");

      return myformat.format(date);
    } catch (Exception e) {
      return "-";
    }
  }








  public static String formatTime(long mills) throws Exception {
    try {
      if (mills == 0L)
        return "-";
      Date date = null;
      Calendar ca = Calendar.getInstance();
      ca.setTimeInMillis(mills);
      date = ca.getTime();


      SimpleDateFormat myformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

      return myformat.format(date);
    } catch (Exception e) {
      return "-";
    }
  }








  public static String formatTimeNoSecond(Date date) { return DATETIME_NOSECOND_FORMAT.format(date); }







  public static String getCurrentDate() {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    Date date = new Date();
    return formatter.format(date);
  }

  public static String getCurrentDate(String format) {
    SimpleDateFormat formatter = new SimpleDateFormat(format);
    Date date = new Date();
    return formatter.format(date);
  }






  public static String getCurrentTime() {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = new Date();
    return formatter.format(date);
  }






  public static long getCurrentTimeMillis() {
    Calendar c = Calendar.getInstance();
    return c.getTimeInMillis();
  }










  public static Date getDate(int year, int month, int date) { return getDate(year, month, date, 0, 0, 0); }













  public static Date getDate(int year, int month, int date, int hourOfDay, int minute, int second) {
    Calendar cal = Calendar.getInstance();
    cal.set(year, month - 1, date, hourOfDay, minute, second);
    return cal.getTime();
  }

  public static String getDate(long time, String format) {
    SimpleDateFormat formater = new SimpleDateFormat(format);
    return formater.format(new Date(time));
  }







  public static Date getDateByDateString(String timeString) {
    Date date = new Date();
    try {
      date = parse(timeString, "yy-MM-dd");
    } catch (ParseException e) {
      e.printStackTrace();
    }
    return date;
  }







  public static String getDateString(Date date) {
    if (date != null) {
      return (new SimpleDateFormat("yyyy-MM-dd")).format(date);
    }
    return "";
  }








  public static String getDateString(long millseconds) { return (new SimpleDateFormat("yyyy-MM-dd")).format(new Date(millseconds)); }









  public static String getDateString(String formater) { return (new SimpleDateFormat(formater)).format(new Date()); }








  public static Date getDateTimeByTimeString(String timeString) {
    Date date = new Date();
    try {
      date = parse(timeString, "yy-MM-dd HH:mm:ss");
    } catch (ParseException e) {
      e.printStackTrace();
    }
    return date;
  }








  public static String getDateTimeString(Date date) { return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(date); }










  public static String getDateTimeString(Date date, String format) { return (new SimpleDateFormat(format)).format(date); }










  public static String getDateTimeString(long millseconds) { return getDate(millseconds, "yyyy-MM-dd HH:mm:ss"); }









  public static String getDayDate(long time) { return getDate(time, "yyyyMMdd"); }


  public static int getDayOfWeek(Date date) {
    Calendar calendar = new GregorianCalendar();
    calendar.setTime(date);
    return calendar.get(7);
  }


  public static long getDaySeparate(Date date1, Date date2) { return (date2.getTime() - date1.getTime()) / 86400000L; }











  public static int getDaysOfMonth(int year, int mon) {
    Calendar cal = Calendar.getInstance();
    cal.set(1, year);
    cal.set(2, mon - 1);
    return cal.getActualMaximum(5);
  }








  public static String getDurationTime(Date time) {
    if (BeanUtils.isEmpty(time))
      return "";
    Long millseconds = Long.valueOf(getTime(time, new Date()));
    return getTime(millseconds);
  }







  public static String getFormatString(long millseconds, String format) {
    if (format == null || format.trim().length() == 0) {
      format = "yyyy-MM-dd";
    }
    format = format.trim();
    return (new SimpleDateFormat(format)).format(new Date(millseconds));
  }








  public static long getMillsByDateString(String strDate) {
    Calendar cal = Calendar.getInstance();
    if (strDate != null && strDate.trim().length() > 9) {
      strDate = strDate.trim();
      try {
        int year = Integer.parseInt(strDate.substring(0, 4));
        int month = Integer.parseInt(strDate.substring(5, 7)) - 1;
        int date = Integer.parseInt(strDate.substring(8, 10));
        cal.set(year, month, date, 0, 0, 0);
        String str = String.valueOf(cal.getTimeInMillis());
        return Long.parseLong(str.substring(0, str.length() - 3) + "000");
      }
      catch (Exception exception) {}
    }



    return 0L;
  }








  public static long getMillsByDateTimeString(String strDateTime) {
    Calendar cal = Calendar.getInstance();
    if (strDateTime != null && strDateTime.trim().length() > 18) {
      strDateTime = strDateTime.trim();
      try {
        int year = Integer.parseInt(strDateTime.substring(0, 4));
        int month = Integer.parseInt(strDateTime.substring(5, 7)) - 1;
        int date = Integer.parseInt(strDateTime.substring(8, 10));
        int hour = Integer.parseInt(strDateTime.substring(11, 13));
        int minute = Integer.parseInt(strDateTime.substring(14, 16));
        int second = Integer.parseInt(strDateTime.substring(17, 19));
        cal.set(year, month, date, hour, minute, second);
        return cal.getTimeInMillis();
      } catch (Exception exception) {}
    }



    return 0L;
  }









  public static long getMillsByTime(String strTime) throws Exception {
    try {
      if (strTime.length() != 19 && strTime.length() != 10) {
        throw new Exception("the time string is wrong.");
      }

      int year = Integer.parseInt(strTime.substring(0, 4));
      int month = Integer.parseInt(strTime.substring(5, 7)) - 1;
      int day = Integer.parseInt(strTime.substring(8, 10));

      if (year < 1000 || year > 3000) {
        throw new Exception("the year is wrong.");
      }

      if (month < 0 || month > 12) {
        throw new Exception("the month is wrong.");
      }

      if (day < 1 || day > 31) {
        throw new Exception("the day is wrong");
      }

      Calendar ca = Calendar.getInstance();
      if (strTime.length() == 19) {
        int hour = Integer.parseInt(strTime.substring(11, 13));
        int minute = Integer.parseInt(strTime.substring(14, 16));
        int second = Integer.parseInt(strTime.substring(17, 19));

        if (hour < 0 || hour > 24) {
          throw new Exception("the hour is wrong.");
        }

        if (minute < 0 || minute > 60) {
          throw new Exception("the minute is wrong.");
        }

        if (second < 0 || second > 60) {
          throw new Exception("the second is wrong.");
        }

        ca.set(year, month, day, hour, minute, second);
      } else if (strTime.length() == 10) {
        ca.set(year, month, day, 0, 0, 0);
      }
      return ca.getTimeInMillis();
    } catch (Exception e) {
      e.printStackTrace();
      return -1L;
    }
  }






  public static long getMillsByToday() {
    String str = getDateString("yyyy-MM-dd");
    str = String.valueOf(getMillsByDateString(str));
    return Long.parseLong(str.substring(0, str.length() - 3) + "000");
  }








  public static Date getNextDays(Date date, int days) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.add(5, days);
    return cal.getTime();
  }







  public static long getNextDays(int days) {
    Calendar cal = Calendar.getInstance();
    cal.add(5, days);
    String str = String.valueOf(cal.getTimeInMillis());
    return Long.parseLong(str.substring(0, str.length() - 3) + "000");
  }











  public static long getNextTime(int timeUnit, int interval, long timeMill) {
    Calendar ca = Calendar.getInstance();
    ca.setTimeInMillis(timeMill);
    switch (timeUnit) {
      case 0:
        ca.add(13, interval);
















        return ca.getTimeInMillis();case 1: ca.add(12, interval); return ca.getTimeInMillis();case 2: ca.add(10, interval); return ca.getTimeInMillis();case 3: ca.add(5, interval); return ca.getTimeInMillis();case 4: ca.add(2, interval); return ca.getTimeInMillis();
    }
    return 0L;
  }





  public static String getNowByString(String style) {
    if (null == style || "".equals(style)) {
      style = "yyyy-MM-dd HH:mm:ss";
    }
    return format(new Date(), style);
  }










  public static int getSecondDiff(Date endTime, Date startTime) {
    long start = startTime.getTime();
    long end = endTime.getTime();
    return (int)((end - start) / 1000L);
  }


  public static long getTime(Date startTime, Date endTime) { return endTime.getTime() - startTime.getTime(); }








  public static String getTime(Long millseconds) {
    String time = "";
    if (millseconds == null) {
      return "";
    }
    int days = (int)millseconds.longValue() / 1000 / 60 / 60 / 24;
    if (days > 0) {
      time = time + days + "天";
    }
    long hourMillseconds = millseconds.longValue() - (days * 1000 * 60 * 60 * 24);
    int hours = (int)hourMillseconds / 1000 / 60 / 60;
    if (hours > 0) {
      time = time + hours + "小时";
    }
    long minuteMillseconds = millseconds.longValue() - (days * 1000 * 60 * 60 * 24) - (hours * 1000 * 60 * 60);
    int minutes = (int)minuteMillseconds / 1000 / 60;
    if (minutes > 0) {
      time = time + minutes + "分钟";
    }
    return time;
  }







  public static String getTimeByMills(long mills) throws Exception {
    try {
      SimpleDateFormat myformat;
      if (mills == 0L)
        return "-";
      Date date = null;
      Calendar ca = Calendar.getInstance();
      ca.setTimeInMillis(mills);
      date = ca.getTime();


      if (ca.get(11) == 0 && ca.get(12) == 0 && ca.get(13) == 0) {
        myformat = new SimpleDateFormat("yyyy-MM-dd");
      } else {
        myformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      }
      return myformat.format(date);
    } catch (Exception e) {
      return "-";
    }
  }








  public static String getTimeDiff(String startTime, String endTime) {
    try {
      String tmp = "";
      SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      ParsePosition pos = new ParsePosition(0);
      ParsePosition pos1 = new ParsePosition(0);
      Date dt1 = formatter.parse(startTime, pos);
      Date dt2 = formatter.parse(endTime, pos1);
      long lDiff = dt2.getTime() - dt1.getTime();
      int days = (int)(lDiff / 86400000L);
      if (days > 0) {
        lDiff -= (days * 1000 * 60 * 60 * 24);
        tmp = tmp + days + "天";
      }
      int hours = (int)(lDiff / 3600000L);
      if (hours > 0)
        lDiff -= (hours * 1000 * 60 * 60);
      tmp = tmp + hours + "小时";
      int minute = (int)(lDiff / 60000L);
      tmp = tmp + minute + "分钟";
      return tmp;
    } catch (Exception e) {
      e.printStackTrace();
      return "-1";
    }
  }









  public static int getWeekDayOfMonth(int year, int mon) {
    Calendar cal = Calendar.getInstance();
    cal.set(year, mon - 1, 1);
    return cal.get(7);
  }








  public static boolean isTimeLarge(String startTime, String endTime) {
    try {
      SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      ParsePosition pos = new ParsePosition(0);
      ParsePosition pos1 = new ParsePosition(0);
      Date dt1 = formatter.parse(startTime, pos);
      Date dt2 = formatter.parse(endTime, pos1);
      long lDiff = dt2.getTime() - dt1.getTime();
      return (lDiff > 0L);
    } catch (Exception e) {

      return false;
    }
  }

  public static Timestamp[] oneDay(Date date) {
    Calendar calendar = new GregorianCalendar();
    calendar.setTime((date != null) ? date : new Date());
    calendar.set(11, 0);
    calendar.set(12, 0);
    calendar.set(13, 0);
    calendar.set(14, 0);

    Timestamp[] array = new Timestamp[2];
    array[0] = new Timestamp(calendar.getTimeInMillis());

    calendar.add(5, 1);
    calendar.add(14, -1);
    array[1] = new Timestamp(calendar.getTimeInMillis());

    return array;
  }

  public static Timestamp[] oneDay(String date) {
    Date d = null;
    if (date != null && date.length() == 8) {
      d = parseDate(date, new String[] { "yyyyMMdd" });
    }
    return oneDay(d);
  }

  public static Date onlyDate(Date time) {
    Calendar calendar = new GregorianCalendar();
    calendar.setTime(time);
    calendar.set(11, 0);
    calendar.set(12, 0);
    calendar.set(13, 0);
    calendar.set(14, 0);
    return calendar.getTime();
  }









  public static Date parse(String dateString) {
    try {
      if (dateString.trim().indexOf(" ") > 0 && dateString.trim().indexOf(".") > 0)
        return new Timestamp(TIMESTAMP_FORMAT.parse(dateString).getTime());
      if (dateString.trim().indexOf(" ") > 0) {

        if (dateString.trim().indexOf(":") != dateString.trim().lastIndexOf(":")) {
          return new Timestamp(DATETIME_FORMAT.parse(dateString).getTime());
        }
        return new Timestamp(DATETIME_NOSECOND_FORMAT.parse(dateString).getTime());
      }
      if (dateString.indexOf(":") > 0) {

        if (dateString.trim().indexOf(":") != dateString.trim().lastIndexOf(":")) {
          return new Time(TIME_FORMAT.parse(dateString).getTime());
        }
        return new Time(TIME_NOSECOND_FORMAT.parse(dateString).getTime());
      }

      return new Date(DATE_FORMAT.parse(dateString).getTime());
    } catch (Exception e) {
      return null;
    }
  }



  public static boolean isDate(String dateString) { return (parse(dateString) != null); }












  public static Date parse(String dateString, String style) throws ParseException {
    DateFormat dateFormat = new SimpleDateFormat(style);
    return dateFormat.parse(dateString);
  }


  public static Date parseDate(String text) { return parseDate(text, new String[] { "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd" }); }



  public static Date parseDate(String text, String[] dateFormatPatterns) { return parseDate(text, null, dateFormatPatterns); }



  public static Date parseDate(String text, TimeZone zone) { return parseDate(text, zone, new String[] { "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd" }); }


  public static Date parseDate(String text, TimeZone zone, String[] dateFormatPatterns) {
    if (dateFormatPatterns != null) {
      String[] arrayOfString;
      int j = (arrayOfString = dateFormatPatterns).length;
      for (int i = 0; i < j; ) {
        String pattern = arrayOfString[i];
        try {
          SimpleDateFormat parser = new SimpleDateFormat(pattern);
          if (zone != null)
            parser.setTimeZone(zone);
          return parser.parse(text);
        } catch (Exception localException) {
          i++;
        }
      }
    }



    throw new RuntimeException("Unparseable date: " + text);
  }









  public static Date parseDateTime(String dateString) throws ParseException { return DATETIME_FORMAT.parse(dateString); }


  public static Date parseTime(String dateString) throws ParseException {
    if (dateString.trim().indexOf(" ") > 0) {
      String[] d = dateString.trim().split(" ");
      if (dateString.trim().indexOf(":") != dateString.trim().lastIndexOf(":")) {
        return new Timestamp(TIME_FORMAT.parse(d[1]).getTime());
      }
      return new Timestamp(TIME_NOSECOND_FORMAT.parse(d[1]).getTime());
    }
    if (dateString.indexOf(":") > 0) {

      if (dateString.trim().indexOf(":") != dateString.trim().lastIndexOf(":")) {
        return new Time(TIME_FORMAT.parse(dateString).getTime());
      }
      return new Time(TIME_NOSECOND_FORMAT.parse(dateString).getTime());
    }

    return new Date(DATETIME_FORMAT.parse(dateString).getTime());
  }









  public static Date parseTimeNoSecond(String dateString) throws ParseException { return DATETIME_NOSECOND_FORMAT.parse(dateString); }









  public static Date string2Date(String string, String pattern) {
    try {
      return (new SimpleDateFormat(pattern)).parse(string);
    } catch (ParseException e) {
      throw new IllegalArgumentException("无法将字符串[" + string + "]按格式[" + pattern + "]转换为日期", e);
    }
  }









  public static int getDayofweek(String date) {
    Calendar cal = Calendar.getInstance();

    if (date.equals("")) {
      cal.setTime(new Date(System.currentTimeMillis()));
    } else {
      cal.setTime(new Date(getDateByStr2(date).getTime()));
    }
    return cal.get(7);
  }

  public static Date getDateByStr2(String dd) {
    Date date;
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");

    try {
      date = sd.parse(dd);
    } catch (ParseException e) {
      date = null;
      e.printStackTrace();
    }
    return date;
  }
}
